﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using PACKETPARSERMAX20.CORE;

namespace PACKETPARSERMAX20.CORE
{
    public class BinaryFileReader
    {
        public class Header
        {
            public string HeaderName = "";
            public byte[] HeaderThree;
            public UInt16 ClientBuild = 0;
            public string Country = "";
            public string SessionKey = "";

            public Header(System.IO.BinaryReader br)
            {
                br.BaseStream.Position = 0;
                HeaderName = BinaryFileReader.ReadString(br, 3);
                HeaderThree = br.ReadBytes(3);
                ClientBuild = br.ReadUInt16(); //s_genericWriter.Write(s_clientInfo.build);
                Country = BinaryFileReader.ReadString(br, 4); // s_genericWriter.Write(s_clientInfo.country);
                SessionKey = BinaryFileReader.ReadHex(br, 20);//br.BaseStream.Position += 20; // s_genericWriter.Write(new byte[20]);
                //string skip = BinaryFileReader.ReadString(br); 
                br.BaseStream.Position += 64; //s_genericWriter.Write(new byte[0x40]);



            }
        }

        public System.IO.BinaryReader br = null;
        public System.IO.FileStream fs = null;
        public Header header;
        public int index = 0;
        public string file = "";

        public BinaryFileReader(string pFile)
        {
            file = pFile;
            fs = new System.IO.FileStream(pFile, System.IO.FileMode.Open);
            br = new System.IO.BinaryReader(fs);

            header = new Header(br);
        }

        ~BinaryFileReader()
        {
            fs.Close();
            br.Close();
        }

        public void Reopen()
        {
            fs.Close();
            br.Close();

            fs = new System.IO.FileStream(file, System.IO.FileMode.Open);
            br = new System.IO.BinaryReader(fs);

            header = new Header(br);
        }

        public PACKETPARSERMAX20.CORE.Packet GetNextPacket()
        {
            PACKETPARSERMAX20.CORE.Packet packet = null;
            try
            {
                if (br.BaseStream.Position != br.BaseStream.Length)
                {
                    index++;
                    byte direction = br.ReadByte();
                    DateTime time = Time_T2DateTime(br.ReadUInt32());
                    UInt32 ticks = br.ReadUInt32();
                    int len = 0;
                    uint opcode = 0;

                    if (direction == 204)
                    {
                        len = br.ReadInt32() - 4;
                        opcode = br.ReadUInt32();
                    }
                    else
                    {
                        len = br.ReadInt32() - 2;
                        opcode = br.ReadUInt16();
                    }

                    if (direction == 255)
                    {
                        direction = 1;
                    }
                    else
                    {
                        direction = 0;
                    }
                    packet = new PACKETPARSERMAX20.CORE.Packet(index, time, direction, opcode, br.ReadBytes(len), len, header.ClientBuild, ticks);

                }
            }
            catch (Exception exc)
            {
                packet = null;
                Console.WriteLine(exc);
            }
            return packet;
        }

        public static string ReadString(System.IO.BinaryReader br, int len)
        {

            StringBuilder tsb = new StringBuilder();
            for (int i = 0; i < len; i++)
            {
                byte t = br.ReadByte();
                if (t != 0)
                {
                    tsb.Append(char.ConvertFromUtf32((int)t));
                }
            }
            return tsb.ToString();

        }

        public static string ReadString(System.IO.BinaryReader br)
        {
            StringBuilder tsb = new StringBuilder();
            try
            {
                char tbBlock;
                while ((tbBlock = br.ReadChar()) != 0)
                {
                    tsb.Append(tbBlock);
                }
            }
            catch //(Exception ex)
            {
                // Reader.BaseStream.Position++;
                //whatever
            }
            return tsb.ToString();
        }

        public static string ReadHex(System.IO.BinaryReader br, int len)
        {
            byte[] bytes = br.ReadBytes(len);


            StringBuilder sb = new StringBuilder();

            foreach (byte b in bytes)
            {
                sb.Append(b.ToString("X4"));
            }

            return sb.ToString();
        }

        public static DateTime Time_T2DateTime(uint time_t)
        {
            long win32FileTime = 10000000 * (long)time_t + 116444736000000000;
            return DateTime.FromFileTimeUtc(win32FileTime).ToLocalTime();
        }
    }
}
